home *** CD-ROM | disk | FTP | other *** search
- /*
- * tkMacWindowMgr.c --
- *
- * Implements common window manager functions for the Macintosh.
- *
- * Copyright (c) 1995-1997 Sun Microsystems, Inc.
- *
- * See the file "license.terms" for information on usage and redistribution
- * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
- *
- * SCCS: @(#) tkMacWindowMgr.c 1.50 97/08/07 14:47:39
- */
-
- #include <Events.h>
- #include <Dialogs.h>
- #include <EPPC.h>
- #include <Windows.h>
- #include <ToolUtils.h>
- #include <DiskInit.h>
- #include <LowMem.h>
- #include <Timer.h>
-
- #include "tkInt.h"
- #include "tkPort.h"
- #include "tkMacInt.h"
-
- #define TK_DEFAULT_ABOUT 128
-
- /*
- * Declarations of global variables defined in this file.
- */
-
- int tkMacAppInFront = true; /* Boolean variable for determining
- * if we are the frontmost app. */
- Tk_Window tkMacFocusWin = NULL; /* Window to which all mouse
- * events will be reported. */
-
- /*
- * Non-standard event types that can be passed to HandleEvent.
- * These are defined and used by Netscape's plugin architecture.
- */
- #define getFocusEvent (osEvt + 16)
- #define loseFocusEvent (osEvt + 17)
- #define adjustCursorEvent (osEvt + 18)
-
- /*
- * Declarations of static variables used in this file.
- */
-
- static int gEatButtonUp = 0; /* 1 if we need to eat the next
- * up event */
- static Tk_Window gGrabWinPtr = NULL; /* Current grab window, NULL if no grab. */
- static Tk_Window gKeyboardWinPtr = NULL; /* Current keyboard grab window. */
- static RgnHandle gDamageRgn = NULL; /* Damage region used for handling
- * screen updates. */
- /*
- * Forward declarations of procedures used in this file.
- */
-
- static void BringWindowForward _ANSI_ARGS_((WindowRef wRef));
- static int CheckEventsAvail _ANSI_ARGS_((void));
- static int GenerateActivateEvents _ANSI_ARGS_((EventRecord *eventPtr,
- Window window));
- static int GenerateFocusEvents _ANSI_ARGS_((EventRecord *eventPtr,
- Window window));
- static int GenerateKeyEvent _ANSI_ARGS_((EventRecord *eventPtr,
- Window window));
- static int GenerateUpdateEvent _ANSI_ARGS_((EventRecord *eventPtr,
- Window window));
- static void GenerateUpdates _ANSI_ARGS_((RgnHandle updateRgn,
- TkWindow *winPtr));
- static int GeneratePollingEvents _ANSI_ARGS_((void));
- static int GeneratePollingEvents2 _ANSI_ARGS_((Window window));
- static OSErr TellWindowDefProcToCalcRegions _ANSI_ARGS_((WindowRef wRef));
- static int WindowManagerMouse _ANSI_ARGS_((EventRecord *theEvent,
- Window window));
-
-
- /*
- *----------------------------------------------------------------------
- *
- * WindowManagerMouse --
- *
- * This function determines if a button event is a "Window Manager"
- * function or an event that should be passed to Tk's event
- * queue.
- *
- * Results:
- * Return true if event was placed on Tk's event queue.
- *
- * Side effects:
- * Depends on where the button event occurs.
- *
- *----------------------------------------------------------------------
- */
-
- static int
- WindowManagerMouse(
- EventRecord *eventPtr, /* Macintosh event record. */
- Window window) /* Window pointer. */
- {
- WindowRef whichWindow, frontWindow;
- Tk_Window tkwin;
- Point where, where2;
- int xOffset, yOffset;
- short windowPart;
-
- frontWindow = FrontWindow();
-
- /*
- * The window manager only needs to know about mouse down events
- * and sometimes we need to "eat" the mouse up. Otherwise, we
- * just pass the event to Tk.
- */
- if (eventPtr->what == mouseUp) {
- if (gEatButtonUp) {
- gEatButtonUp = false;
- return false;
- }
- return TkGenerateButtonEvent(eventPtr->where.h, eventPtr->where.v,
- window, TkMacButtonKeyState());
- }
-
- windowPart = FindWindow(eventPtr->where, &whichWindow);
- tkwin = Tk_IdToWindow(tkDisplayList->display, window);
- switch (windowPart) {
- case inSysWindow:
- SystemClick(eventPtr, (GrafPort *) whichWindow);
- return false;
- case inDrag:
- if (whichWindow != frontWindow) {
- if (!(eventPtr->modifiers & cmdKey)) {
- if ((gGrabWinPtr != NULL) && (gGrabWinPtr != tkwin)) {
- SysBeep(1);
- return false;
- }
- }
- }
-
- /*
- * Call DragWindow to move the window around. It will
- * also eat the mouse up event.
- */
- SetPort((GrafPort *) whichWindow);
- where.h = where.v = 0;
- LocalToGlobal(&where);
- DragWindow(whichWindow, eventPtr->where,
- &tcl_macQdPtr->screenBits.bounds);
- gEatButtonUp = false;
-
- where2.h = where2.v = 0;
- LocalToGlobal(&where2);
- if (EqualPt(where, where2)) {
- return false;
- }
-
- TkMacWindowOffset(whichWindow, &xOffset, &yOffset);
- where2.h -= xOffset;
- where2.v -= yOffset;
- TkGenWMConfigureEvent(tkwin, where2.h, where2.v,
- -1, -1, TK_LOCATION_CHANGED);
- return true;
- case inGrow:
- case inContent:
- if (whichWindow != frontWindow ) {
- /*
- * This click moves the window forward. We don't want
- * the corasponding mouse-up to be reported to the application
- * or else it will mess up some Tk scripts.
- */
- if ((gGrabWinPtr != NULL) && (gGrabWinPtr != tkwin)) {
- SysBeep(1);
- return false;
- }
- BringWindowForward(whichWindow);
- gEatButtonUp = true;
- SetPort((GrafPort *) whichWindow);
- return false;
- } else {
- /*
- * Generally the content region is the domain of Tk
- * sub-windows. However, one exception is the grow
- * region. A button down in this area will be handled
- * by the window manager. Note: this means that Tk
- * may not get button down events in this area!
- */
-
- if (TkMacGrowToplevel(whichWindow, eventPtr->where) == true) {
- return true;
- } else {
- return TkGenerateButtonEvent(eventPtr->where.h,
- eventPtr->where.v, window, TkMacButtonKeyState());
- }
- }
- case inGoAway:
- if (TrackGoAway( whichWindow, eventPtr->where)) {
- if (tkwin == NULL) {
- return false;
- }
- TkGenWMDestroyEvent(tkwin);
- return true;
- }
- return false;
- case inMenuBar:
- {
- int oldMode;
- KeyMap theKeys;
-
- GetKeys(theKeys);
- oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
- TkMacClearMenubarActive();
- TkMacHandleMenuSelect(MenuSelect(eventPtr->where),
- theKeys[1] & 4);
- Tcl_SetServiceMode(oldMode);
- return true; /* TODO: may not be on event on queue. */
- }
- case inZoomIn:
- case inZoomOut:
- if (TkMacZoomToplevel(whichWindow, eventPtr->where, windowPart)
- == true) {
- return true;
- } else {
- return false;
- }
- default:
- return false;
- }
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * TkAboutDlg --
- *
- * Displays the default Tk About box. This code uses Macintosh
- * resources to define the content of the About Box.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- void
- TkAboutDlg()
- {
- DialogPtr aboutDlog;
- short itemHit = -9;
-
- aboutDlog = GetNewDialog(128, NULL, (void*)(-1));
-
- if (!aboutDlog) {
- return;
- }
-
- SelectWindow((WindowRef) aboutDlog);
-
- while (itemHit != 1) {
- ModalDialog( NULL, &itemHit);
- }
- DisposDialog(aboutDlog);
- aboutDlog = NULL;
-
- SelectWindow(FrontWindow());
-
- return;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * GenerateUpdateEvent --
- *
- * Given a Macintosh update event this function generates all the
- * X update events needed by Tk.
- *
- * Results:
- * True if event(s) are generated - false otherwise.
- *
- * Side effects:
- * Additional events may be place on the Tk event queue.
- *
- *----------------------------------------------------------------------
- */
-
- static int
- GenerateUpdateEvent(
- EventRecord *eventPtr, /* Incoming Mac event */
- Window window) /* Root X window for event. */
- {
- WindowRef macWindow;
- register TkWindow *winPtr;
-
- winPtr = (TkWindow *) Tk_IdToWindow(tkDisplayList->display, window);
-
- if (winPtr == NULL) {
- return false;
- }
-
- if (gDamageRgn == NULL) {
- gDamageRgn = NewRgn();
- }
-
- /*
- * After the call to BeginUpdate the visable region (visRgn) of the
- * window is equal to the intersection of the real visable region and
- * the update region for this event. We use this region in all of our
- * calculations.
- */
-
- if (eventPtr->message != NULL) {
- macWindow = (WindowRef) TkMacGetDrawablePort(window);
- BeginUpdate(macWindow);
- GenerateUpdates(macWindow->visRgn, winPtr);
- EndUpdate(macWindow);
- return true;
- } else {
- /*
- * This event didn't come from the system. This might
- * occur if we are running from inside of Netscape.
- * In this we shouldn't call BeginUpdate as the vis region
- * may be NULL.
- */
- RgnHandle rgn;
- Rect bounds;
-
- rgn = NewRgn();
- TkMacWinBounds(winPtr, &bounds);
- RectRgn(rgn, &bounds);
- GenerateUpdates(rgn, winPtr);
- DisposeRgn(rgn);
- return true;
- }
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * GenerateUpdates --
- *
- * Given a Macintosh update region and a Tk window this function
- * geneates a X damage event for the window if it is within the
- * update region. The function will then recursivly have each
- * damaged window generate damage events for its child windows.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Additional events may be place on the Tk event queue.
- *
- *----------------------------------------------------------------------
- */
-
- static void
- GenerateUpdates(
- RgnHandle updateRgn,
- TkWindow *winPtr)
- {
- TkWindow *childPtr;
- XEvent event;
- Rect bounds;
-
- TkMacWinBounds(winPtr, &bounds);
-
- if (bounds.top > (*updateRgn)->rgnBBox.bottom ||
- (*updateRgn)->rgnBBox.top > bounds.bottom ||
- bounds.left > (*updateRgn)->rgnBBox.right ||
- (*updateRgn)->rgnBBox.left > bounds.right ||
- !RectInRgn(&bounds, updateRgn)) {
- return;
- }
-
- event.xany.serial = Tk_Display(winPtr)->request;
- event.xany.send_event = false;
- event.xany.window = Tk_WindowId(winPtr);
- event.xany.display = Tk_Display(winPtr);
-
- event.type = Expose;
-
- /*
- * Compute the bounding box of the area that the damage occured in.
- */
-
- /*
- * CopyRgn(TkMacVisableClipRgn(winPtr), rgn);
- * TODO: this call doesn't work doing resizes!!!
- */
- RectRgn(gDamageRgn, &bounds);
- SectRgn(gDamageRgn, updateRgn, gDamageRgn);
- OffsetRgn(gDamageRgn, -bounds.left, -bounds.top);
- event.xexpose.x = (**gDamageRgn).rgnBBox.left;
- event.xexpose.y = (**gDamageRgn).rgnBBox.top;
- event.xexpose.width = (**gDamageRgn).rgnBBox.right -
- (**gDamageRgn).rgnBBox.left;
- event.xexpose.height = (**gDamageRgn).rgnBBox.bottom -
- (**gDamageRgn).rgnBBox.top;
- event.xexpose.count = 0;
-
- Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
-
- /*
- * Generate updates for the children of this window
- */
-
- for (childPtr = winPtr->childList; childPtr != NULL;
- childPtr = childPtr->nextPtr) {
- if (!Tk_IsMapped(childPtr) || Tk_IsTopLevel(childPtr)) {
- continue;
- }
-
- GenerateUpdates(updateRgn, childPtr);
- }
-
- /*
- * Generate updates for any contained windows
- */
-
- if (Tk_IsContainer(winPtr)) {
- childPtr = TkpGetOtherWindow(winPtr);
- if (childPtr != NULL && Tk_IsMapped(childPtr)) {
- GenerateUpdates(updateRgn, childPtr);
- }
-
- /*
- * NOTE: Here we should handle out of process embedding.
- */
-
- }
-
- return;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * TkGenerateButtonEvent --
- *
- * Given a global x & y position and the button key status this
- * procedure generates the appropiate X button event. It also
- * handles the state changes needed to implement implicit grabs.
- *
- * Results:
- * True if event(s) are generated - false otherwise.
- *
- * Side effects:
- * Additional events may be place on the Tk event queue.
- * Grab state may also change.
- *
- *----------------------------------------------------------------------
- */
-
- int
- TkGenerateButtonEvent(
- int x, /* X location of mouse */
- int y, /* Y location of mouse */
- Window window, /* X Window containing button event. */
- unsigned int state) /* Button Key state suitable for X event */
- {
- WindowRef whichWin, frontWin;
- Point where;
- Tk_Window tkwin;
- int dummy;
-
- /*
- * ButtonDown events will always occur in the front
- * window. ButtonUp events, however, may occur anywhere
- * on the screen. ButtonUp events should only be sent
- * to Tk if in the front window or during an implicit grab.
- */
- where.h = x;
- where.v = y;
- FindWindow(where, &whichWin);
- frontWin = FrontWindow();
-
- if ((frontWin == NULL) || (frontWin != whichWin && gGrabWinPtr == NULL)) {
- return false;
- }
-
- tkwin = Tk_IdToWindow(tkDisplayList->display, window);
-
- GlobalToLocal(&where);
- if (tkwin != NULL) {
- tkwin = Tk_TopCoordsToWindow(tkwin, where.h, where.v, &dummy, &dummy);
- }
-
- Tk_UpdatePointer(tkwin, x, y, state);
-
- return true;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * GenerateActivateEvents --
- *
- * Generate Activate/Deactivate events from a Macintosh Activate
- * event. Note, the activate-on-foreground bit must be set in the
- * SIZE flags to ensure we get Activate/Deactivate in addition to
- * Susspend/Resume events.
- *
- * Results:
- * Returns true if events were generate.
- *
- * Side effects:
- * Queue events on Tk's event queue.
- *
- *----------------------------------------------------------------------
- */
-
- static int
- GenerateActivateEvents(
- EventRecord *eventPtr, /* Incoming Mac event */
- Window window) /* Root X window for event. */
- {
- TkWindow *winPtr;
-
- winPtr = (TkWindow *) Tk_IdToWindow(tkDisplayList->display, window);
- if (winPtr == NULL || winPtr->window == None) {
- return false;
- }
-
- TkGenerateActivateEvents(winPtr,
- (eventPtr->modifiers & activeFlag) ? 1 : 0);
- return true;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * XSetInputFocus --
- *
- * Change the focus window for the application.
- *
- * Results:
- * None.
- *
- * Side effects:
- * May change the window used by Key events.
- *
- *----------------------------------------------------------------------
- */
-
- void
- XSetInputFocus(
- Display* display,
- Window focus,
- int revert_to,
- Time time)
- {
- Tk_Window tkwin;
-
- display->request++;
- tkwin = Tk_IdToWindow(tkDisplayList->display, focus);
- if (tkwin == NULL) {
- return;
- }
-
- tkMacFocusWin = tkwin;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * TkpChangeFocus --
- *
- * This procedure is a syub on the Mac because we always own the
- * focus if we are a front most application.
- *
- * Results:
- * None.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- void
- TkpChangeFocus(winPtr, force)
- TkWindow *winPtr; /* Window that is to receive the X focus. */
- int force; /* Non-zero means claim the focus even
- * if it didn't originally belong to
- * topLevelPtr's application. */
- {
- Tk_Window tkwin;
-
- /*
- * Change the focus on the Mac. (The same as XSetFocus.) Don't
- * set the focus to a window that's marked override-redirect.
- */
-
- if (winPtr->atts.override_redirect) {
- return;
- }
- tkDisplayList->display->request++;
- tkwin = Tk_IdToWindow(tkDisplayList->display, winPtr->window);
- if (tkwin == NULL) {
- return;
- }
-
- tkMacFocusWin = tkwin;
-
- /*
- * Remember the current serial number for the X server and issue
- * a dummy server request. This marks the position at which we
- * changed the focus, so we can distinguish FocusIn and FocusOut
- * events on either side of the mark.
- */
-
- winPtr->mainPtr->focusSerial = NextRequest(winPtr->display);
- return;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * GenerateFocusEvents --
- *
- * Generate FocusIn/FocusOut events from a Macintosh Activate
- * event. Note, the activate-on-foreground bit must be set in
- * the SIZE flags to ensure we get Activate/Deactivate in addition
- * to Susspend/Resume events.
- *
- * Results:
- * Returns true if events were generate.
- *
- * Side effects:
- * Queue events on Tk's event queue.
- *
- *----------------------------------------------------------------------
- */
-
- static int
- GenerateFocusEvents(
- EventRecord *eventPtr, /* Incoming Mac event */
- Window window) /* Root X window for event. */
- {
- XEvent event;
- Tk_Window tkwin;
-
- tkwin = Tk_IdToWindow(tkDisplayList->display, window);
- if (tkwin == NULL) {
- return false;
- }
-
- /*
- * Generate FocusIn and FocusOut events. This event
- * is only sent to the toplevel window.
- */
- if (eventPtr->modifiers & activeFlag) {
- event.xany.type = FocusIn;
- tkMacFocusWin = tkwin;
- } else {
- event.xany.type = FocusOut;
- }
-
- event.xany.serial = tkDisplayList->display->request;
- event.xany.send_event = False;
- event.xfocus.display = tkDisplayList->display;
- event.xfocus.window = window;
- event.xfocus.mode = NotifyNormal;
- event.xfocus.detail = NotifyDetailNone;
-
- Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
- return true;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * GenerateKeyEvent --
- *
- * Given Macintosh keyUp, keyDown & autoKey events this function
- * generates the appropiate X key events.
- *
- * Results:
- * True if event(s) are generated - false otherwise.
- *
- * Side effects:
- * Additional events may be place on the Tk event queue.
- *
- *----------------------------------------------------------------------
- */
-
- static int
- GenerateKeyEvent(
- EventRecord *eventPtr, /* Incoming Mac event */
- Window window) /* Root X window for event. */
- {
- Point where;
- Tk_Window tkwin;
- XEvent event;
-
- /*
- * The focus window is set during FocusIn events and
- * explicit calls to XSetInputFocus. We just use that
- * value. Tk will make sure the event gets to the *real*
- * window the focus belongs to.
- */
- tkwin = tkMacFocusWin;
- if (tkwin == NULL) {
- return false;
- }
- where.v = eventPtr->where.v;
- where.h = eventPtr->where.h;
-
- event.xany.send_event = False;
- event.xkey.same_screen = true;
- event.xkey.subwindow = None;
- event.xkey.time = TkpGetMS();
-
- event.xkey.x_root = where.h;
- event.xkey.y_root = where.v;
- GlobalToLocal(&where);
- Tk_TopCoordsToWindow(tkwin, where.h, where.v,
- &event.xkey.x, &event.xkey.y);
- event.xkey.keycode = eventPtr->message;
-
- event.xany.serial = Tk_Display(tkwin)->request;
- event.xkey.window = Tk_WindowId(tkwin);
- event.xkey.display = Tk_Display(tkwin);
- event.xkey.root = XRootWindow(Tk_Display(tkwin), 0);
- event.xkey.state = TkMacButtonKeyState();
-
- if (eventPtr->what == keyDown) {
- event.xany.type = KeyPress;
- Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
- } else if (eventPtr->what == keyUp) {
- event.xany.type = KeyRelease;
- Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
- } else {
- /*
- * Autokey events send multiple XKey events.
- *
- * Note: the last KeyRelease will always be missed with
- * this scheme. However, most Tk scripts don't look for
- * KeyUp events so we should be OK.
- */
- event.xany.type = KeyRelease;
- Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
- event.xany.type = KeyPress;
- Tk_QueueWindowEvent(&event, TCL_QUEUE_TAIL);
- }
- return true;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * GeneratePollingEvents --
- *
- * This function polls the mouse position and generates X Motion,
- * Enter & Leave events. The cursor is also updated at this
- * time.
- *
- * Results:
- * True if event(s) are generated - false otherwise.
- *
- * Side effects:
- * Additional events may be place on the Tk event queue.
- * The cursor may be changed.
- *
- *----------------------------------------------------------------------
- */
-
- static int
- GeneratePollingEvents()
- {
- Tk_Window tkwin, rootwin;
- Window window;
- WindowRef whichwindow, frontWin;
- Point whereLocal, whereGlobal;
- Boolean inContentRgn;
- short part;
- int local_x, local_y;
- int generatedEvents = false;
-
- /*
- * First we get the current mouse position and determine
- * what Tk window the mouse is over (if any).
- */
- frontWin = FrontWindow();
- if (frontWin == NULL) {
- return false;
- }
- SetPort((GrafPort *) frontWin);
-
- GetMouse(&whereLocal);
- whereGlobal = whereLocal;
- LocalToGlobal(&whereGlobal);
-
- part = FindWindow(whereGlobal, &whichwindow);
- inContentRgn = (part == inContent || part == inGrow);
-
- if ((frontWin != whichwindow) || !inContentRgn) {
- tkwin = NULL;
- } else {
- window = TkMacGetXWindow(whichwindow);
- rootwin = Tk_IdToWindow(tkDisplayList->display, window);
- if (rootwin == NULL) {
- tkwin = NULL;
- } else {
- tkwin = Tk_TopCoordsToWindow(rootwin, whereLocal.h, whereLocal.v,
- &local_x, &local_y);
- }
- }
-
- /*
- * The following call will generate the appropiate X events and
- * adjust any state that Tk must remember.
- */
- Tk_UpdatePointer(tkwin, whereGlobal.h, whereGlobal.v, TkMacButtonKeyState());
-
- /*
- * Finally, we make sure the proper cursor is installed. The installation
- * is polled to 1) make our resize hack work, and 2) make sure we have the
- * proper cursor even if someone else changed the cursor out from under
- * us.
- */
- if ((gGrabWinPtr == NULL) && (part == inGrow) &&
- TkMacResizable((TkWindow *) tkwin) &&
- (TkMacGetScrollbarGrowWindow((TkWindow *) tkwin) == NULL)) {
- TkMacInstallCursor(1);
- } else {
- TkMacInstallCursor(0);
- }
-
- return true;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * GeneratePollingEvents2 --
- *
- * This function polls the mouse position and generates X Motion,
- * Enter & Leave events. The cursor is also updated at this
- * time. NOTE: this version is for Netscape!!!
- *
- * Results:
- * True if event(s) are generated - false otherwise.
- *
- * Side effects:
- * Additional events may be place on the Tk event queue.
- * The cursor may be changed.
- *
- *----------------------------------------------------------------------
- */
-
- static int
- GeneratePollingEvents2(
- Window window)
- {
- Tk_Window tkwin, rootwin;
- WindowRef whichwindow, frontWin;
- Point whereLocal, whereGlobal;
- int local_x, local_y;
- int generatedEvents = false;
- Rect bounds;
-
- /*
- * First we get the current mouse position and determine
- * what Tk window the mouse is over (if any).
- */
- frontWin = FrontWindow();
- if (frontWin == NULL) {
- return false;
- }
- SetPort((GrafPort *) frontWin);
-
- GetMouse(&whereLocal);
- whereGlobal = whereLocal;
- LocalToGlobal(&whereGlobal);
-
- /*
- * Determine if we are in a Tk window or not.
- */
- whichwindow = (WindowRef) TkMacGetDrawablePort(window);
- if (whichwindow != frontWin) {
- tkwin = NULL;
- } else {
- rootwin = Tk_IdToWindow(tkDisplayList->display, window);
- TkMacWinBounds((TkWindow *) rootwin, &bounds);
- if (!PtInRect(whereLocal, &bounds)) {
- tkwin = NULL;
- } else {
- tkwin = Tk_TopCoordsToWindow(rootwin, whereLocal.h, whereLocal.v,
- &local_x, &local_y);
- }
- }
-
- /*
- * The following call will generate the appropiate X events and
- * adjust any state that Tk must remember.
- */
- Tk_UpdatePointer(tkwin, whereGlobal.h, whereGlobal.v, TkMacButtonKeyState());
-
- /*
- * Finally, we make sure the proper cursor is installed. The installation
- * is polled to 1) make our resize hack work, and 2) make sure we have the
- * proper cursor even if someone else changed the cursor out from under
- * us.
- */
- TkMacInstallCursor(0);
-
- return true;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * TkMacButtonKeyState --
- *
- * Returns the current state of the button & modifier keys.
- *
- * Results:
- * A bitwise inclusive OR of a subset of the following:
- * Button1Mask, ShiftMask, LockMask, ControlMask, Mod?Mask,
- * Mod?Mask.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- unsigned int
- TkMacButtonKeyState()
- {
- unsigned int state = 0;
- KeyMap theKeys;
-
- if (Button() & !gEatButtonUp) {
- state |= Button1Mask;
- }
-
- GetKeys(theKeys);
-
- if (theKeys[1] & 2) {
- state |= LockMask;
- }
-
- if (theKeys[1] & 1) {
- state |= ShiftMask;
- }
-
- if (theKeys[1] & 8) {
- state |= ControlMask;
- }
-
- if (theKeys[1] & 32768) {
- state |= Mod1Mask; /* command key */
- }
-
- if (theKeys[1] & 4) {
- state |= Mod2Mask; /* option key */
- }
-
- return state;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * XGrabKeyboard --
- *
- * Simulates a keyboard grab by setting the focus.
- *
- * Results:
- * Always returns GrabSuccess.
- *
- * Side effects:
- * Sets the keyboard focus to the specified window.
- *
- *----------------------------------------------------------------------
- */
-
- int
- XGrabKeyboard(
- Display* display,
- Window grab_window,
- Bool owner_events,
- int pointer_mode,
- int keyboard_mode,
- Time time)
- {
- gKeyboardWinPtr = Tk_IdToWindow(display, grab_window);
- return GrabSuccess;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * XUngrabKeyboard --
- *
- * Releases the simulated keyboard grab.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Sets the keyboard focus back to the value before the grab.
- *
- *----------------------------------------------------------------------
- */
-
- void
- XUngrabKeyboard(
- Display* display,
- Time time)
- {
- gKeyboardWinPtr = NULL;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * XQueryPointer --
- *
- * Check the current state of the mouse. This is not a complete
- * implementation of this function. It only computes the root
- * coordinates and the current mask.
- *
- * Results:
- * Sets root_x_return, root_y_return, and mask_return. Returns
- * true on success.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- Bool
- XQueryPointer(
- Display* display,
- Window w,
- Window* root_return,
- Window* child_return,
- int* root_x_return,
- int* root_y_return,
- int* win_x_return,
- int* win_y_return,
- unsigned int* mask_return)
- {
- Point where;
-
- GetMouse(&where);
- LocalToGlobal(&where);
- *root_x_return = where.h;
- *root_y_return = where.v;
- *mask_return = TkMacButtonKeyState();
- return True;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * TkMacGenerateTime --
- *
- * Returns the total number of ticks from startup This function
- * is used to generate the time of generated X events.
- *
- * Results:
- * Returns the current time (ticks from startup).
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- Time
- TkMacGenerateTime()
- {
- return (Time) LMGetTicks();
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * TkMacConvertEvent --
- *
- * This function converts a Macintosh event into zero or more
- * Tcl events.
- *
- * Results:
- * Returns 1 if event added to Tcl queue, 0 otherwse.
- *
- * Side effects:
- * May add events to Tcl's event queue.
- *
- *----------------------------------------------------------------------
- */
-
- int
- TkMacConvertEvent(
- EventRecord *eventPtr)
- {
- WindowRef whichWindow;
- Window window;
- int eventFound = false;
-
- switch (eventPtr->what) {
- case nullEvent:
- case adjustCursorEvent:
- if (GeneratePollingEvents()) {
- eventFound = true;
- }
- break;
- case updateEvt:
- whichWindow = (WindowRef)eventPtr->message;
- window = TkMacGetXWindow(whichWindow);
- if (GenerateUpdateEvent(eventPtr, window)) {
- eventFound = true;
- }
- break;
- case mouseDown:
- case mouseUp:
- FindWindow(eventPtr->where, &whichWindow);
- window = TkMacGetXWindow(whichWindow);
- if (WindowManagerMouse(eventPtr, window)) {
- eventFound = true;
- }
- break;
- case autoKey:
- case keyDown:
- /*
- * Handle menu-key events here. If it is *not*
- * a menu key - just fall through to handle as a
- * normal key event.
- */
- if ((eventPtr->modifiers & cmdKey) == cmdKey) {
- long menuResult;
- int oldMode;
-
- oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL);
- menuResult = MenuKey(eventPtr->message & charCodeMask);
- Tcl_SetServiceMode(oldMode);
-
- if (HiWord(menuResult) != 0) {
- TkMacHandleMenuSelect(menuResult, false);
- break;
- }
- }
- case keyUp:
- whichWindow = FrontWindow();
- window = TkMacGetXWindow(whichWindow);
- eventFound |= GenerateKeyEvent(eventPtr, window);
- break;
- case activateEvt:
- window = TkMacGetXWindow((WindowRef) eventPtr->message);
- eventFound |= GenerateActivateEvents(eventPtr, window);
- eventFound |= GenerateFocusEvents(eventPtr, window);
- break;
- case getFocusEvent:
- eventPtr->modifiers |= activeFlag;
- window = TkMacGetXWindow((WindowRef) eventPtr->message);
- eventFound |= GenerateFocusEvents(eventPtr, window);
- break;
- case loseFocusEvent:
- eventPtr->modifiers &= ~activeFlag;
- window = TkMacGetXWindow((WindowRef) eventPtr->message);
- eventFound |= GenerateFocusEvents(eventPtr, window);
- break;
- case kHighLevelEvent:
- TkMacDoHLEvent(eventPtr);
- /* TODO: should return true if events were placed on event queue. */
- break;
- case osEvt:
- /*
- * Do clipboard conversion.
- */
- switch ((eventPtr->message & osEvtMessageMask) >> 24) {
- case mouseMovedMessage:
- if (GeneratePollingEvents()) {
- eventFound = true;
- }
- break;
- case suspendResumeMessage:
- if (!(eventPtr->message & resumeFlag)) {
- TkSuspendClipboard();
- }
- tkMacAppInFront = (eventPtr->message & resumeFlag);
- break;
- }
- break;
- case diskEvt:
- /*
- * Disk insertion.
- */
- if (HiWord(eventPtr->message) != noErr) {
- Point pt;
-
- DILoad();
- pt.v = pt.h = 120; /* parameter ignored in sys 7 */
- DIBadMount(pt, eventPtr->message);
- DIUnload();
- }
- break;
- }
-
- return eventFound;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * TkMacConvertTkEvent --
- *
- * This function converts a Macintosh event into zero or more
- * Tcl events.
- *
- * Results:
- * Returns 1 if event added to Tcl queue, 0 otherwse.
- *
- * Side effects:
- * May add events to Tcl's event queue.
- *
- *----------------------------------------------------------------------
- */
-
- int
- TkMacConvertTkEvent(
- EventRecord *eventPtr,
- Window window)
- {
- int eventFound = false;
- Point where;
-
- switch (eventPtr->what) {
- case nullEvent:
- case adjustCursorEvent:
- if (GeneratePollingEvents2(window)) {
- eventFound = true;
- }
- break;
- case updateEvt:
- if (GenerateUpdateEvent(eventPtr, window)) {
- eventFound = true;
- }
- break;
- case mouseDown:
- case mouseUp:
- GetMouse(&where);
- LocalToGlobal(&where);
- eventFound |= TkGenerateButtonEvent(where.h, where.v,
- window, TkMacButtonKeyState());
- break;
- case autoKey:
- case keyDown:
- /*
- * Handle menu-key events here. If it is *not*
- * a menu key - just fall through to handle as a
- * normal key event.
- */
- if ((eventPtr->modifiers & cmdKey) == cmdKey) {
- long menuResult = MenuKey(eventPtr->message & charCodeMask);
-
- if (HiWord(menuResult) != 0) {
- TkMacHandleMenuSelect(menuResult, false);
- break;
- }
- }
- case keyUp:
- eventFound |= GenerateKeyEvent(eventPtr, window);
- break;
- case activateEvt:
- eventFound |= GenerateActivateEvents(eventPtr, window);
- eventFound |= GenerateFocusEvents(eventPtr, window);
- break;
- case getFocusEvent:
- eventPtr->modifiers |= activeFlag;
- eventFound |= GenerateFocusEvents(eventPtr, window);
- break;
- case loseFocusEvent:
- eventPtr->modifiers &= ~activeFlag;
- eventFound |= GenerateFocusEvents(eventPtr, window);
- break;
- case kHighLevelEvent:
- TkMacDoHLEvent(eventPtr);
- /* TODO: should return true if events were placed on event queue. */
- break;
- case osEvt:
- /*
- * Do clipboard conversion.
- */
- switch ((eventPtr->message & osEvtMessageMask) >> 24) {
- case mouseMovedMessage:
- if (GeneratePollingEvents2(window)) {
- eventFound = true;
- }
- break;
- case suspendResumeMessage:
- if (!(eventPtr->message & resumeFlag)) {
- TkSuspendClipboard();
- }
- tkMacAppInFront = (eventPtr->message & resumeFlag);
- break;
- }
- break;
- case diskEvt:
- /*
- * Disk insertion.
- */
- if (HiWord(eventPtr->message) != noErr) {
- Point pt;
-
- DILoad();
- pt.v = pt.h = 120; /* parameter ignored in sys 7 */
- DIBadMount(pt, eventPtr->message);
- DIUnload();
- }
- break;
- }
-
- return eventFound;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * CheckEventsAvail --
- *
- * Checks to see if events are available on the Macintosh queue.
- * This function looks for both queued events (eg. key & button)
- * and generated events (update).
- *
- * Results:
- * True is events exist, false otherwise.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- static int
- CheckEventsAvail()
- {
- QHdrPtr evPtr;
- WindowPeek macWinPtr;
-
- evPtr = GetEvQHdr();
- if (evPtr->qHead != NULL) {
- return true;
- }
-
- macWinPtr = (WindowPeek) FrontWindow();
- while (macWinPtr != NULL) {
- if (!EmptyRgn(macWinPtr->updateRgn)) {
- return true;
- }
- macWinPtr = macWinPtr->nextWindow;
- }
- return false;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * TkpSetCapture --
- *
- * This function captures the mouse so that all future events
- * will be reported to this window, even if the mouse is outside
- * the window. If the specified window is NULL, then the mouse
- * is released.
- *
- * Results:
- * None.
- *
- * Side effects:
- * Sets the capture flag and captures the mouse.
- *
- *----------------------------------------------------------------------
- */
-
- void
- TkpSetCapture(
- TkWindow *winPtr) /* Capture window, or NULL. */
- {
- while ((winPtr != NULL) && !Tk_IsTopLevel(winPtr)) {
- winPtr = winPtr->parentPtr;
- }
- gGrabWinPtr = (Tk_Window) winPtr;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * TkMacWindowOffset --
- *
- * Determines the x and y offset from the orgin of the toplevel
- * window dressing (the structure region, ie. title bar) and the
- * orgin of the content area.
- *
- * Results:
- * The x & y offset in pixels.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- void
- TkMacWindowOffset(
- WindowRef wRef,
- int *xOffset,
- int *yOffset)
- {
- OSErr err = noErr;
- WindowPeek wPeek = (WindowPeek) wRef;
- RgnHandle strucRgn = wPeek->strucRgn;
- RgnHandle contRgn = wPeek->contRgn;
- Rect strucRect, contRect;
-
- if (!EmptyRgn(strucRgn) && !EmptyRgn(contRgn)) {
- strucRect = (**strucRgn).rgnBBox;
- contRect = (**contRgn).rgnBBox;
- } else {
- /*
- * The current window's regions are not up to date.
- * Probably because the window isn't visable. What we
- * will do is save the old regions, have the window calculate
- * what the regions should be, and then restore it self.
- */
- strucRgn = NewRgn( );
- contRgn = NewRgn( );
-
- if (!strucRgn || !contRgn) {
- err = MemError( );
- } else {
- CopyRgn(wPeek->strucRgn, strucRgn);
- CopyRgn(wPeek->contRgn, contRgn);
-
- if (!(err = TellWindowDefProcToCalcRegions(wRef))) {
- strucRect = (**(wPeek->strucRgn)).rgnBBox;
- contRect = (**(wPeek->contRgn)).rgnBBox;
- }
-
- CopyRgn(strucRgn, wPeek->strucRgn);
- CopyRgn(contRgn, wPeek->contRgn);
- }
-
- if (contRgn) {
- DisposeRgn(contRgn);
- }
-
- if (strucRgn) {
- DisposeRgn(strucRgn);
- }
- }
-
- if (!err) {
- *xOffset = contRect.left - strucRect.left;
- *yOffset = contRect.top - strucRect.top;
- } else {
- *xOffset = 0;
- *yOffset = 0;
- }
-
- return;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * TellWindowDefProcToCalcRegions --
- *
- * Force a Macintosh window to recalculate it's content and
- * structure regions.
- *
- * Results:
- * An OS error.
- *
- * Side effects:
- * The windows content and structure regions may be updated.
- *
- *----------------------------------------------------------------------
- */
-
- static OSErr
- TellWindowDefProcToCalcRegions(
- WindowRef wRef)
- {
- OSErr err = noErr;
- SInt8 hState;
- Handle wdef = ((WindowPeek) wRef)->windowDefProc;
-
- /*
- * Load and lock the window definition procedure for
- * the window.
- */
- hState = HGetState(wdef);
- if (!(err = MemError())) {
- LoadResource(wdef);
- if (!(err = ResError())) {
- MoveHHi(wdef);
- err = MemError();
- if (err == memLockedErr) {
- err = noErr;
- } else if (!err) {
- HLock(wdef);
- err = MemError();
- }
- }
- }
-
- /*
- * Assuming there are no errors we now call the window definition
- * procedure to tell it to calculate the regions for the window.
- */
- if (err == noErr) {
- (void) CallWindowDefProc((WindowDefProcPtr) *wdef,
- GetWVariant(wRef), wRef, wCalcRgns, 0);
-
- HSetState(wdef, hState);
- if (!err) {
- err = MemError();
- }
- }
-
- return err;
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * BringWindowForward --
- *
- * Bring this background window to the front. We also set state
- * so Tk thinks the button is currently up.
- *
- * Results:
- * None.
- *
- * Side effects:
- * The window is brought forward.
- *
- *----------------------------------------------------------------------
- */
-
- static void
- BringWindowForward(
- WindowRef wRef)
- {
- SelectWindow(wRef);
- }
-
- /*
- *----------------------------------------------------------------------
- *
- * TkpGetMS --
- *
- * Return a relative time in milliseconds. It doesn't matter
- * when the epoch was.
- *
- * Results:
- * Number of milliseconds.
- *
- * Side effects:
- * None.
- *
- *----------------------------------------------------------------------
- */
-
- unsigned long
- TkpGetMS()
- {
- long long * int64Ptr;
- UnsignedWide micros;
-
- Microseconds(µs);
- int64Ptr = (long long *) µs;
-
- /*
- * We need 64 bit math to do this. This is available in CW 11
- * and on. Other's will need to use a different scheme.
- */
-
- *int64Ptr /= 1000;
-
- return (long) *int64Ptr;
- }
-